#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include "Util.hpp"
#include <jsoncpp/json/json.h>

// #define MYSELF 1

// 给网络版本计算器定制协议
namespace protocol_ns
{
#define SEP " "
#define SEP_LNE strlen(SEP) // 绝对不能写成sizeof
#define HEADER_SEP "\r\n"
#define HEADER_SEP_LEN strlen("\r\n")

    // "长度"\r\n"协议号\r\n""_x _op _y"\r\n
    
    // "长度"\r\n""_x _op _y"\r\n
    //"10 + 20" => "7"\r\n""10 + 20"\r\n => 报头 + 有效载荷
    // 请求/响应 = 报头\r\n有效载荷\r\n
    std::string AddHeader(const std::string &str)
    {
        std::cout << "AddHeader 之前:\n " << str << std::endl;
        std::string s = std::to_string(str.size());
        s += HEADER_SEP;
        s += str;
        s += HEADER_SEP;

        std::cout << "AddHeader 之后:\n " << s << std::endl;
        return s;
    }

    //"7"\r\n""10 + 20"\r\n => "10 + 20" 去报头
    std::string RemoveHeader(const std::string &str, int len)
    {
        std::cout << "RemoveHeader 之前:\n " << str << std::endl;
        std::string res = str.substr(str.size() - HEADER_SEP_LEN - len, len);

        std::cout << "RemoveHeader 之后:\n " << res << std::endl;
        return res;
    }

    // const & :表示输入
    // *: 输出
    // &: 输入输出
    int ReadPackage(int sock, std::string &inbuffer, std::string *package)//想通过它*package，来输出内容，所以是*
    {
        std::cout << "ReadPackage inbuffer 之前:\n " << inbuffer << std::endl;
        // 边读取
        char buffer[1024];
        ssize_t s = recv(sock, buffer, sizeof(buffer - 1), 0); // 读取到buffer中，大小为buffer
        if (s <= 0)
            return -1;
        buffer[s] = 0;
        inbuffer += buffer;

        std::cout << "ReadPackage inbuffer 之中:\n " << inbuffer << std::endl;

        // 边分析，"7"\r\n""10 + 20"\r\n
        auto pos = inbuffer.find(HEADER_SEP);
        if (pos == std::string::npos)
            return 0;                                 // inbuffer我没看到\r\n，什么都没动
        std::string lenStr = inbuffer.substr(0, pos); // 获取了头部字符串
        int len = Util::toInt(lenStr);                //"123" -> 123， inbuffer还是什么都没动
        int targetPackageLen = lenStr.size() + len + 2 * HEADER_SEP_LEN;//inbuffer还是什么都没动,只是做分析,只要拿到有效载荷，就知道长度
        if (inbuffer.size() < targetPackageLen)//小于，所以inbuffer我的缓冲区里不可能存在一个完整报文，我期望的报文总大小为targetPackageLen
            return 0;                                    // inbuffer我没看到什么都没动
        *package = inbuffer.substr(0, targetPackageLen); // 提取到了整个报文,inbuffer我没看到什么都没动
        inbuffer.erase(0, targetPackageLen);             // 从inbuffer中直接移除整个报文

        std::cout << "ReadPackage inbuffer 之后:\n " << inbuffer << std::endl;

        return len;
    }

    // Request和Response都要提供序列化和反序列化功能
    // 1.自己手写
    // 2.用别人的 -- json、xml、protcol

    // 请求
    class Request
    {
    public:
        Request()
        {
        }
        Request(int x, int y, char op)
            : _x(x), _y(y), _op(op)
        {
        }
        // struct->string
        // 目前想要的：“_x _op _y”
        bool Serialize(std::string *outStr) // 把结果带出去
        {
            *outStr = "";
#ifdef MYSELF
            std::string x_string = std::to_string(_x);
            std::string y_string = std::to_string(_y);

            // 手动序列化
            *outStr = x_string + SEP + _op + SEP + y_string;

            std::cout << "Request Serialize:\n " << *outStr << std::endl;
#else
            Json::Value root; // Value:一种万能对象，接受任意的kv类型
            root["x"] = _x;
            root["y"] = _y;
            root["op"] = _op;
            Json::FastWriter writer; // FastWriter:是用来进行序列化的,一行 struct-> string
            // Json::StyledWriter writer;// StyledWriter:是用来进行序列化的,结构体型

            *outStr = writer.write(root);
#endif
            return true;
        }

        // string->struct
        bool Deserialize(const std::string &inStr) // 把结果带出来
        {
#ifdef MYSELF
            // inStr:10 + 20 =>[0]=>10,[1]=>+,[2]=>20
            // string->vector
            std::vector<std::string> result;
            Util::StringSplit(inStr, SEP, &result);
            if (result.size() != 3)
                return false;
            _x = Util::toInt(result[0]);
            _y = Util::toInt(result[2]);
            if (result[1].size() != 1) // result[1]必须等于1，成功
                return false;
            _op = result[1][0];
            
#else
            Json::Value root;
            Json::Reader reader; // Reader:是用来进行反序列化的
            reader.parse(inStr, root);
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _op = root["op"].asInt();
#endif
            Print();
            return true;
        }

        void Print()
        {
            std::cout << "_x: " << _x << std::endl;
            std::cout << "_y: " << _y << std::endl;
            std::cout << "_op: " << _op << std::endl;
        }
        ~Request()
        {
        }

    public:
        int _x;
        int _y;
        char _op;
    };

    // 响应
    class Response
    {
    public:
        Response() {}
        Response(int result, int code)
            : _result(result), _code(code)
        {
        }

        // struct->string
        bool Serialize(std::string *outStr) // 把结果带出去
        {
            *outStr = "";
#ifdef MYSELF
            //_result _code

            std::string res_string = std::to_string(_result);
            std::string code_string = std::to_string(_code);

            // 手动序列化
            *outStr = res_string + SEP + code_string;

            std::cout << "Response Serialize:\n " << *outStr << std::endl;
#else
            Json::Value root;
            root["result"] = _result;
            root["code"] = _code;
            Json::FastWriter writer;
            *outStr = writer.write(root);
#endif
            return true;
        }

        // string->struct
        bool Deserialize(const std::string &inStr) // 把结果带出来
        {
#ifdef MYSELF
            // 10 0, 10 1
            std::vector<std::string> result;
            Util::StringSplit(inStr, SEP, &result);
            if (result.size() != 2)
                return false;
            _result = Util::toInt(result[0]);
            _code = Util::toInt(result[1]);
#else

            Json::Value root;
            Json::Reader reader; // Reader:是用来进行反序列化的
            reader.parse(inStr, root);
            _result = root["result"].asInt();
            _code = root["code"].asInt();
#endif
            Print();
            return true;
        }

        void Print()
        {
            std::cout << "_result: " << _result << std::endl;
            std::cout << "_code: " << _code << std::endl;
        }
        ~Response() {}

    public:
        int _result;
        int _code; // 0表示成功，1、2、3、4表示不同的错误码
    };
}

